package com.u.social.sale.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.u.social.sale.entity.SeckillStock;
import com.u.social.sale.mapper.SeckillStockMapper;
import com.u.social.sale.service.ISeckillStockService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.Arrays;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Alex Wu
 * @since 2025-03-13
 */
@Service
public class SeckillStockServiceImpl extends ServiceImpl<SeckillStockMapper, SeckillStock> implements ISeckillStockService {


    @Autowired
    private RedisTemplate redisTemplate;

    private final String REDIS_KEY_PREFIX = "secKill:product:stock:";


    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Scheduled(cron = "0 0 17 * * ?") // 秒杀时间前17点执行
    public void syncLikeStatus() {
        System.out.println("执行定时任务");
        // 需要先查询数据库
        SeckillStock seckillStock = this.getById(100L);

        // 更新到缓存当中
        redisTemplate.opsForValue().set("REDIS_KEY_PREFIX" + seckillStock.getProductId() , seckillStock.getStockNum());
    }

    @Override
    public boolean secKill(Long productId) {
        Object stock = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX + productId);
        if (stock == null || (Integer) stock < 1) {
            return false;
        }
        // 预扣库存,避免其他多个未生效请求打到订单系统,此使用 lua 脚本进行原子扣减库存
        String script =
                "if tonumber(redis.call('get', KEYS[1])) > 0 then " +
                        "   redis.call('decr', KEYS[1]); " +
                        "   return 1; " +
                        "else " +
                        "   return 0; " +
                        "end";

        Boolean result = (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection -> {
            return connection.eval(script.getBytes(), ReturnType.BOOLEAN, 1, (REDIS_KEY_PREFIX + productId).getBytes());
        });

        if (result == null || !result) {
            // 扣减失败
            return false;
        }

        Long userId = 123L;

        // 扣减成功，发送的MQ ,执行下订单
        rocketMQTemplate.syncSend("secKill-topic", userId + ":" + productId);
        return true;
    }
}
